from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QMessageBox, QTextEdit
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent
from PyQt5.QtCore import QUrl, QTimer, QThread, pyqtSignal
from PyQt5.QtGui import QFont
from asrProject_ui import Ui_MainWindow
import sys
import time
from ppasr.predict import PPASRPredictor  # 确保你已安装 PPASR 模型
import thulac
from bs4 import BeautifulSoup  # 用于清理 HTML 标签
import re  # 正则表达式
class AnalysisThread(QThread):
    """
    异步分析线程
    """
    analysis_done = pyqtSignal(int, int, str, int, int)

    def __init__(self, transcription):
        super().__init__()
        self.transcription = transcription

    def run(self):
        # 调用分析方法
        result = self.analyze_transcription(self.transcription)
        if result is not None:
            word_repeats, phrase_repeats, formatted_text, dp_count, ij_count = result
            # 发射分析结果信号
            self.analysis_done.emit(word_repeats, phrase_repeats, formatted_text, dp_count, ij_count)
        else:
            # 如果分析结果为 None，发射默认值
            self.analysis_done.emit(0, 0, self.transcription, 0, 0)

    def analyze_transcription(self, transcription):
        print(f"进入 analyze_transcription 方法，转写文本：{transcription}")
        if not transcription:
            print("转写文本为空，无法进行分析")
            return None

        # 使用 thulac 进行分词
        thu1 = thulac.thulac(seg_only=True)  # 只进行分词，不进行词性标注
        words = thu1.cut(transcription, text=True).split()  # 分词结果为字符串，使用空格分隔

        # 打印分词结果
        print("分词结果:", "/ ".join(words))

        # 初始化统计变量
        word_repeats = 0  # 重复字统计
        phrase_repeats = 0  # 重复词组统计
        dp_count = 0  # "呃" 和 "啊" 的统计
        ij_count = 0  # "嗯" 的统计

        # 初始化格式化文本
        formatted_text = list(transcription)  # 使用列表方便修改

        # 统计连续重复的单个字（排除特定的语气词）
        pattern = re.compile(r'(.)\1{1,}', re.DOTALL)
        for match in pattern.finditer(transcription):
            if match.group(1) not in ['呃', '啊', '嗯']:
                word_repeats += 1
                start, end = match.span()
                for i in range(start, end):
                    formatted_text[i] = f'<span style="background-color: #FFF697;">{transcription[i]}</span>'

        # 统计连续重复的两个字符的词组
        phrase_pattern = re.compile(r'(\b\w{2}\b)\s+\1', re.DOTALL)
        for match in phrase_pattern.finditer(" ".join(words)):
            phrase_repeats += 1
            start, end = match.span()
            for i in range(start, end):
                formatted_text[i] = f'<span style="background-color: #D9F1FF;">{transcription[i]}</span>'

        # 统计语气词 "呃" 和 "啊"（DP）
        for i, char in enumerate(transcription):
            if char in ['呃', '啊']:
                dp_count += 1
                formatted_text[i] = f'<span style="background-color: #BAF9FE;">{char}</span>'

        # 统计语气词 "嗯"（IJ）
        for i, char in enumerate(transcription):
            if char == '嗯':
                ij_count += 1
                formatted_text[i] = f'<span style="background-color: #CDFFCC;">{char}</span>'

        # 将列表转换回字符串
        formatted_text = ''.join(formatted_text)

        return word_repeats, phrase_repeats, formatted_text, dp_count, ij_count


class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.selected_file = None
        self.save_path = None
        self.media_player = QMediaPlayer()

        # 初始化预测器
        self.predictor = PPASRPredictor(model_tag='conformer_streaming_fbank_wenetspeech')

        # 绑定按钮功能
        self.btn_chooseRecognition.clicked.connect(self.choose_audio)
        self.btn_SpeechRecognition.clicked.connect(self.start_transcription)
        self.btn_save.clicked.connect(self.choose_save_path)
        self.btn_clear.clicked.connect(self.clear_text_edit_1)
        self.btn_show.clicked.connect(self.play_audio)

        self.textEdit_1.textChanged.connect(self.on_text_changed)

        # 添加一个标志位，用于控制是否允许分析
        self.allow_analysis = True

        # 延迟触发的定时器
        self.delay_timer = QTimer(self)
        self.delay_timer.setSingleShot(True)
        self.delay_timer.timeout.connect(self.on_text_changed_delayed)

        # 保存上一次的文本内容
        self.previous_text = ""
        # 连接进度条和播放器
        self.horizontalSlider.valueChanged.connect(self.media_player.setPosition)
        self.media_player.positionChanged.connect(self.update_slider_position)
        self.media_player.durationChanged.connect(self.set_slider_range)

    def choose_audio(self):
        self.selected_file, _ = QFileDialog.getOpenFileName(
            self, "选择音频文件", "",
            "音频文件 (*.mp3 *.wav *.ogg *.flac *.aac);;视频文件 (*.mp4 *.avi *.mov *.mkv)"
        )
        if self.selected_file:
            print(f"选择的音频文件：{self.selected_file}")

    def play_audio(self):
        if self.selected_file:
            self.media_player.setMedia(QMediaContent(QUrl.fromLocalFile(self.selected_file)))
            self.media_player.play()
        else:
            QMessageBox.warning(self, "警告", "请先选择音频文件")

    def update_slider_position(self, position):
            self.horizontalSlider.setValue(position)

    def set_slider_range(self, duration):
        self.horizontalSlider.setMaximum(duration)

    def start_transcription(self):
        if not self.selected_file:
            QMessageBox.warning(self, "警告", "请先选择音频文件")
            return

        # 禁用分析标志位
        self.allow_analysis = False

        # 记录识别开始时间
        start_time = time.time()

        try:
            # 调用模型进行语音识别
            result = self.predictor.predict_long(audio_data=self.selected_file, use_pun=False)

            # 检查 result 是否为 None 或无效
            if result is None or 'text' not in result or not result['text']:
                QMessageBox.warning(self, "警告", "语音识别失败，请检查音频文件是否有效")
                return

            # 记录识别结束时间
            end_time = time.time()
            elapsed_time = end_time - start_time

            # 清理 HTML 标签
            clean_text = self.clean_html(result['text'])

            # 处理重复字和重复词组
            word_repeats, phrase_repeats, formatted_text, dp_count, ij_count = self.analyze_transcription(clean_text)

            # 在 textEdit_1 中显示识别结果
            self.textEdit_1.setHtml(formatted_text)
            # 打印识别结果和时间
            print(f"识别结果: {clean_text}, 得分: {result['score']}")
            print(f"识别时间: {elapsed_time:.2f} 秒")

            # 更新统计信息
            self.WW_lineEdit.setText(str(word_repeats))  # 显示重复字
            self.PR_lineEdit.setText(str(phrase_repeats))  # 显示重复字组
            self.DP_lineEdit.setText(str(dp_count))  # 显示DP
            self.IJ_lineEdit.setText(str(ij_count))  # 显示IJ
            SLD = word_repeats + phrase_repeats + dp_count
            self.SLD_lineEdit.setText(str(SLD))  # 显示SLD
        except Exception as e:
            print(f"识别异常: {e}")
            #QMessageBox.warning(self, "警告", "识别过程中出现错误")
        finally:
            # 恢复分析标志位
            self.allow_analysis = True

    def choose_save_path(self):
        self.save_path = QFileDialog.getExistingDirectory(self, "选择保存路径")
        if self.save_path:
            print(f"选择的保存路径：{self.save_path}")

    def play_audio(self):
        if self.selected_file:
            self.media_player.setMedia(QMediaContent(QUrl.fromLocalFile(self.selected_file)))
            self.media_player.play()
        else:
            QMessageBox.warning(self, "警告", "请先选择音频文件")

    def clear_text_edit_1(self):
        self.textEdit_1.clear()

    def clean_html(self, text):
        """清理 HTML 标签"""
        soup = BeautifulSoup(text, 'html.parser')
        return soup.get_text()

    def analyze_transcription(self, transcription):
        # 调用异步线程进行分析
        self.analysis_thread = AnalysisThread(transcription)
        self.analysis_thread.analysis_done.connect(self.update_ui)
        self.analysis_thread.start()

    def on_text_changed(self):
        """
        当 textEdit_1 的内容发生变化时，延迟触发分析。
        """
        if not self.allow_analysis:  # 如果标志位为 False，则跳过分析
            return

        current_text = self.textEdit_1.toPlainText()
        if current_text != self.previous_text:  # 如果文本内容发生变化
            self.previous_text = current_text  # 更新上一次的文本内容
            # 每次文本变化时，重新启动定时器
            self.delay_timer.start(500)  # 延迟 500 毫秒后再触发分析

    def on_text_changed_delayed(self):
        """
        延迟触发的分析方法。
        """
        transcription = self.textEdit_1.toPlainText()  # 获取当前文本内容
        if not transcription:
            print("文本为空，无法进行分析")
            return

        # 调用异步分析
        self.analyze_transcription(transcription)

    def update_ui(self, word_repeats, phrase_repeats, formatted_text, dp_count, ij_count):
        """
        更新 UI 的方法
        """
        # 更新 textEdit_1 的内容（带背景色标记）
        self.textEdit_1.setHtml(formatted_text)

        # 更新统计信息
        self.WW_lineEdit.setText(str(word_repeats))  # 显示重复字
        self.PR_lineEdit.setText(str(phrase_repeats))  # 显示重复字组
        self.DP_lineEdit.setText(str(dp_count))  # 显示DP
        self.IJ_lineEdit.setText(str(ij_count))  # 显示IJ
        SLD = word_repeats + phrase_repeats + dp_count
        self.SLD_lineEdit.setText(str(SLD))  # 显示SLD


if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setFont(QFont("WenQuanYi Micro Hei", 12))
    mainWindow = MainWindow()
    mainWindow.show()
    sys.exit(app.exec_())